基础知识
Android 系统架构
Android系统构架是安卓系统的体系结构,android的系统架构和其操作系统一样,采用了分层的架构,一般共分为四层,从高到低分别是:
- Android应用层 - 包括通话短信联系人这种系统级的应用,还包括用户自己安装的第三方应用
- Android应用框架层 - 这一层大部分用Java写的,包括系统服务和四大组件
- Android系统运行层 - 这一层大部分都是C/C++写的,主要是虚拟机 Dalvik/ART ,还有一些第三方库
- Linux内核层 - 包含Linux内核和一些驱动,比如说蓝牙驱动,Camera驱动等等
还有 HAL层-硬件抽象层
Android系统构架主要应用于ARM平台,但不仅限于ARM,通过编译控制,在X86、MAC等体系结构的机器上同样可以运行。
Android进程间通信-binder
- IPC(Inter-Process Communication)进程间通讯
- C(低权限应用)/S(高权限系统服务)
- /dev/binder – framework和app之间IPC通信桥梁
- /dev/hwbinder(8.0之后) – framework和vendor之间的IPC通信桥梁
- /dev/vndbinder(8.0之后) – vendor和vendor之间的IPC通信桥梁
SELinux限制
Android 8.0之后推出厂商升级成本大大降低,8.0之后增加vendor.img镜像 ,攻击面大大减少, 很多厂商的代码不与应用层直接交互, 增加了应用和厂商代码的SELinux限制
Android 内核攻击面
- 应用直达内核路径寥寥无几 – /dev/binder、/dev/ashmem等
- 厂商自定义的驱动设备 – cat /proc/devices
- 应用 -> system_server等 -> 内核
- 应用 -> 系统应用 -> system_server等 -> 内核
Android内核缓释机制
- DAC/ CAP Linux最基本的安全缓释机制
- PXN(Privileged Execute Never)类似于x86中的SMEP,防止内核态执行用户态代码,防御RET2USR攻击,可以通过修改rc4 来绕过。Android 5 arm64后开启,Android通过页表来开启PXN。
- PAN (Privileged Access Never) 类似于x86中的SMAP ,防止内核任意读取用户态数据,Android 8.0之后加入。
- SECCOMP 限制应用程序可以使用的系统调用,增加系统的安全性。shell中执行exp不会受到限制,apk中执行exp会受到seccomp限制,比如无法调到setuid、chroot、mount等。Android 8.0之后影响所有zygote孵化出来的进程。
- KASLR 内核地址空间布局随机化,可以让kernel image映射的地址相对于链接地址有个偏移,利用需要泄露内核信息。Android kernel版本大于4.4之后默认开启。
- AVB (Android Verified Boot 启动时验证)启动时验证boot、system、vendor等是否被篡改,Persistent root 克星。Android 7.0 之后严格执行启动验证,Android 8.0 之后默认集成AVB2.0 ,有回滚保护,防止回滚到有漏洞的版本。
Android 内核漏洞利用基础知识
内核关键数据结构
线程数据结构体,内核栈和hread_info共用一片区域 ,其中 addr_limit 用户态 0x7ffffffff000
1
2
3
4
5
6
7
8
9
10
11
12
13
14union thread_union{
struct thread_info thread_info;
unsigned long stack[THREAD_SIZE/sizeof(lone)];
}
struct thread_info{
unsigned long flag; /*low level flag*/
mm_segment_t addr_limit; /*address limit */
struct task_struct *task;
struct exec_domain *exec_domian; /* execution domain */
struct restart_block restart_block;
int preempt_count;
int cpu;
}进程描述符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17struct task_ struct {
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
void *stack; // contains addr_ limi t
unsigned int flags; /* per process flags, defined below */
...
struct list_ head tasks ;
struct mm struct *mm, *active_ mm;
#ifdef CONFIG COMPAT_ BRK
unsigned brk randomized:1;
...
/* process credentials */
const struct cred __rcu *real_cred; /* objective and real subjective task */
consts truct cred __rcu *ered; /* effective (overridable) subjective task */
char comm[TASK_COMM_LEN] ;
...
struct seccomp seccomp ;
}
安全凭证cred
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18struct cred {
unsigned int usage;
uid_t uid;
gid_t gid;
uid_t suid;
gid_t sgid;
uid_t euid;
gid_t egid;
uid_t fsuid;
gid_t fsgid;
unsigned int securebits;
struct kernel_cap_struct cap_inheritable;
struct kernel_cap_struct Cap_permitted;
struct kernel_cap_struct cap_ef fective;
struct kernel_cap_struct cap_bset;
struct kernel_cap_struct cap_ambient;
void *security; /* subjective LSM security */
};安全凭证 task_secutity 安全域
1
2
3
4
5
6
7
8struct task_ security_ struct {
u32 osid; /* SID prior to last execve */
u32 sid; /* current SID */
u32 exec_sid;/* exec SID */
u32 create_sid;/* fscreate SID */
u32 keycreate_sid; /* keycreate SID */
u32 sockcreate_sid; /* fscreate SID */
};内核关键全局变量
selinux_enforcing
selinux_enabled
init_stack
对于没有KASLR的设备地址固定,偏移固定。
关闭内核缓释机制
1、关闭addr_limit
- 内核线程栈低偏移8字节为addr_limit,将addr_limit 改为-1(0xffffffffffffffff),关闭之后即可任意读写内核。
2、 关闭DAC
- 修改进程安全凭证cred中进程id相关值uid、gid等为init进程的值
3、关闭CAP
- 修改进程安全凭证cred中的cap相关值 cap_inheritable等为init进程的值
4、 关闭SELinux
- 修改selinux_enforcing 为0
- 修改selinux_enbaled 为0
- 修改进程安全凭证cred中的security安全域 osid、sid、exec_sid、create_sid、kercreate_sid、sockcreate_sid为init进程的值
5、关闭SECCOMP
修改thread_info中的flags,将seccomp位置0
1
2修改task_struct 中的seccomp中的mode为0
1
2
3
4struct seccopm {
int mode;
struct seccomp_filter *filter;
}
持久化root
只适用于低版本Android:1
2
3
4
5
6adb shell mount -0 remount,rw /system
adb push su /system/xbin/su
adb shell chown 0.0 /system/xbin/su
adb shell chmod 06755 /system/xbin/su
adb shell mount -0 remount,ro /system
adb install Superuser.apk
高版本(Android 7.0 之后) 无解
Android 内核任意地址读写思路
1、用户态不能直接访问内核态
2、需要借助内核函数完成内核任意地址读写
- 系统调用由内核完成
- 寻找系统调用中搬到参数合法的方式->addr_limit
- read/write、readv/writev、recvmsg/sendmsg 等
Android源码阅读网站
Android环境搭建
本地环境 ubuntu 16.04
- SDK安装
https://developer.android.com/studio/releases/platform-tools
下载最新版29(截止2020.1) 确定adb可以使用
安装可参考 https://blog.csdn.net/u011974797/article/details/78973012 - NDK安装
https://developer.android.com/ndk/downloads
下载最新版r20b(截止2020.1)确定ndk-build可以使用
安装可参考 https://blog.csdn.net/fanx9339/article/details/81116332
Android root实验
给定一个含有驱动漏洞的Android虚拟机,通过该驱动漏洞实现root
1.1 确定Android版本号
adb shell getprop ro.build.version.release
1.2 寻找有漏洞的驱动设备
搜索 cdev_init()函数
cdev_init() 加载驱动设备函数
qword_FFFFFFC00055C438 里面注册 dev_open,dev_ioctl等
1.3 提取kernel符号表
python ./vmlinux.py ./test/pixel_vmlinux
1.4 IDA加载kernel并导入符号表
vmlinux.py -> C:\Program Files\IDA x.x\loaders\
1.5 分析漏洞并完成kernel任意地址读写
通过fop发现ioctl中存在任意地址读写漏洞
1.6 提权到root
CVE-2019-2215 复现
影响版本 Android 9.0 kernel 4.4
driver/android/binder.c1
2
3
4
5
6
7
8
9
10
11
12
13
14
15static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned
long arg)
{
...
switch (cmd) {
...
case BINDER_THREAD_EXIT:
binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n",
proc->pid, thread->pid);
binder_free_thread(proc, thread);
thread = NULL;
break;
...
}
}
Android kernel 4.4 driver/android/binder.c1
2
3
4
5
6
7
8
9static int binder_free_thread(struct binder_proc *proc,
struct binder_thread *thread) {
...
if (send_reply)
binder_send_failed_reply(send_reply, BR_DEAD_REPLY);
binder_release_work(&thread->todo);
kfree(thread);
binder_stats_deleted(BINDER_STAT_THREAD);
return active_transactions; }
PoC
1 |
|
##其他命令
连接 Android shell
./adb shell
1、获取手机系统信息( CPU,厂商名称等)
adb shell “cat /system/build.prop | grep “product””
2、获取手机系统版本
adb shell getprop ro.build.version.release
3、获取手机系统api版本
adb shell getprop ro.build.version.sdk
4、获取手机设备型号
adb -d shell getprop ro.product.model
5、获取手机厂商名称
adb -d shell getprop ro.product.brand
6、获取手机的序列号
有两种方式
- 1、 adb get-serialno
- 2、 adb shell getprop ro.serialno
7、获取手机内存信息
adb shell cat /proc/meminfo
8、获取手机存储信息
adb shell df
9、获取手机物理密度
adb shell wm density